;*****************************************************************************************************
;+
; NAME:
;       IGL_PROPERTYEDITOR
;
; PURPOSE:
;
;       This is a slightly modified version of a PROPERTYPANEL object
;       (Catalyst Library). It adds the possibility to filter the
;       objects that are displayed in the tree and to automatically
;       update the tree view when an object is deleted. 
;
;
; AUTHORS:
;
;        RAPHAEL SADOUN
;        Graduate Student
;        Institut d'Astrophysique de Paris
;        98 bis boulevard Arago
;        75014 PARIS FRANCE
;        E-mail: raphael.sadoun@gmail.com
;
; SUPERCLASSES:
;
;       PROPERTYPANEL (Catalyst Library)
;
; SYNTAX:
;
;       panel = Obj_New('IGL_PROPERTYEDITOR',targetObject)
;
;
; CLASS_STRUCTURE:
;
;   class = {IGL_PropertyEditor, $
;           INHERITS PROPERTYPANEL, $ ; This is a PropertyPanel object
;           targetObject:obj_new(), $ ; The object for which we want to show its contents
;           filter:'' $               ; The filter to apply when calling the IGL_ViewContents routine
;           }
;
;
; MODIFICATION_HISTORY:
;
;       Written by: Raphael Sadoun, 24 April 2012
;-
;*****************************************************************************************************
;+
; NAME:
;       IGL_PropertyEditor::MESSAGEHANDLER
;
; PURPOSE:
;
;       This method is where messages sent by other objects to this one
;       get treated. It is written primirarly to handle
;       'OBJECT_DELETED' message from children of the target
;       object. It is called automatically when messages are received.
;
; SYNTAX:
;
;       self -> MessageHandler, title
;
; ARGUMENTS:
;
;       TITLE:   The title of the message.
;
; KEYWORDS:
;
;       DATA:    A keyword that contains any information the sender wishes to pass
;                with the message. It can be empty.
;
;       SENDER:  The object that generated the message
;-
;*****************************************************************************************************
PRO IGL_PropertyEditor::MessageHandler, title, SENDER=sender, DATA=data

  @cat_pro_error_handler

   CASE title OF

      ;; An OBJECT_DELETED message means the sender is about to be
      ;; destroyed. We need to update the tree to reflect this.
      'OBJECT_DELETED': BEGIN

         ;; Turn auto destroy OFF because we don't want the
         ;; object to self destruct just yet.
         sender -> SetProperty, auto_destroy=0

         ;; Remove temporarily the object from all its parents
         sender -> GetProperty, parents=parents
         FOR i=0, n_elements(parents)-1 DO BEGIN
            IF OBJ_VALID(parents[i]) THEN parents[i] -> CatAtom::Remove, sender
         ENDFOR

         ;; Update the tree view
         self -> UpdateTreeBrowser

         ;; Add back the object as a child of its parents
         FOR i=0, n_elements(parents)-1 DO BEGIN
            sender -> AddParent, parents[i]
         ENDFOR

         ;; Turn auto destroy ON 
         sender -> SetProperty, auto_destroy=1
         
      END

      ELSE:

   ENDCASE

   ;; Report completion
   self -> Report, /completed

END


;*****************************************************************************************************
;+
; NAME:
;       IGL_PropertyEditor::UPDATETREEBROWSER
;
; PURPOSE:
;
;       This method is used to reconstruct the tree view in the left
;       base of the PROPERTYPANEL object.
;
; SYNTAX:
;
;       self -> UpdateTreeBrowset, title
;
; ARGUMENTS:
;
;       None.
;
; KEYWORDS:
;
;       None.
;-
;*****************************************************************************************************
PRO IGL_PropertyEditor::UpdateTreeBrowser

  @cat_pro_error_handler

  ;; Make sure there is a valid base widget for the tree
  IF (NOT obj_valid(self.left_base)) THEN return

  ;; Destroy the current tree
  self.left_base -> GetProperty, OChild=treeWidget
  obj_destroy, treeWidget

  ;; Reconstruct the tree view of the target Object
  IF Obj_Valid(self.targetObject) THEN IGL_ViewContents, self.targetObject, Parent=self.left_base, filter=self.filter

  ;; Assign the new tree to the left base of the panel
  self.left_base -> GetProperty, OChild=treeWidget
  self.treeWidget = treeWidget

  ;; Register the panel for OBJECT_DELETED messages produced by the
  ;; children of the target object. This is done to be able to update
  ;; the tree if an object is deleted.  
  children = self.targetObject -> Get(/all,ISA=filter,/recursive_search,count=count)
  FOR i=0, count-1 DO BEGIN
     children[i] -> RegisterForMessage, self, 'OBJECT_DELETED'
  ENDFOR

   
END


;*****************************************************************************************************
;+
; NAME:
;       IGL_PropertyEditor::CLEANUP
;
; PURPOSE:
;
;       This is the IGl_PropertyEditor object class destructor method.
;
; SYNTAX:
;
;       Called automatically when the object is destroyed.
;
; ARGUMENTS:
;
;       None.
;
; KEYWORDS:
;
;       None.
;-
;*****************************************************************************************************
PRO IGL_PropertyEditor::Cleanup

  @cat_pro_error_handler

  ;; Destroy the PROPERTYPANEL superclass
  self -> PropertyPanel::Cleanup

  ;; Report completion
  self -> Report, /Completed

END

;*****************************************************************************************************
;+
; NAME:
;       IGL_PropertyEditor::INIT
;
; PURPOSE:
;
;       This is the IGL_PropertyEditor object class creator method.
;
; SYNTAX:
;
;       Called automatically when the object is created.
;
; ARGUMENTS:
;
;       TARGETOBJECT:    The object for which we want to view the contents.
;
; KEYWORDS:
;
;       FILTER:    Set to a name of an object class. Only objects of
;                  this class (and the derived classes) will be
;                  displayed in the PROPERTYPANEL object. The default
;                  is 'CatAtom'.
;
;       _EXTRA:    Any keyword accepted by the PROPERTYPANEL::Init method
;
;-
;*****************************************************************************************************
FUNCTION IGL_PropertyEditor::Init, targetObject, FILTER=filter, _EXTRA=extra

  @cat_func_error_handler

  ;; Initialize the PROPERTYPANEL superclass
  ok = self -> PropertyPanel::Init(targetObject,title='Property Editor',_extra=extra)
  IF (NOT ok) THEN return, 0

  ;; Populate the object
  IF (n_elements(filter) EQ 0) THEN filter = 'CatAtom'
  self.targetObject = targetObject
  self.filter = filter

  ;; Register the panel for OBJECT_DELETED messages produced by the
  ;; children of the target object. This is done to be able to update
  ;; the tree if an object is deleted.  
  children = targetObject -> Get(/all,ISA=filter,/recursive_search,count=count)
  FOR i=0, count-1 DO BEGIN
     children[i] -> RegisterForMessage, self, 'OBJECT_DELETED'
  ENDFOR

  ;; Reconstruct the tree with the IGL_ViewContents (similar to CATVIEWCONTENTS)
  IF (obj_valid(self.left_base)) THEN BEGIN

     ;; Destroy the current tree 
     self.left_base -> GetProperty, OChild=treeWidget
     obj_destroy, treeWidget
     
     ;; Reconstruct the tree view if we have a valid target
     IF Obj_Valid(self.targetObject) THEN IGL_ViewContents, self.targetObject, Parent=self.left_base, filter=filter

     ;; Assign new the tree to the left base of the panel
     self.left_base -> GetProperty, OChild=treeWidget
     self.treeWidget = treeWidget
     
  ENDIF

  ;; Report completion
  self -> Report, /completed

  return, 1
  
END

;*****************************************************************************************************
;
; NAME:
;       IGL_PROPERTYEDITOR CLASS DEFINITION
;
; PURPOSE:
;
;       This is the IGL_PropertyEditor object's structure definition code.
;
;*****************************************************************************************************
PRO IGL_PropertyEditor__define, class

  COMPILE_OPT idl2, HIDDEN

  class = {IGL_PropertyEditor, $
           INHERITS PROPERTYPANEL, $ ; This is a PropertyPanel object
           targetObject:obj_new(), $ ; The object for which we want to show its contents
           filter:'' $               ; The filter to apply when calling the IGL_ViewContents routine
          }

  struct_hide, class
  
END
